
#include <BPainter>
#include "member_BLayout.h"
#include "member_BSpacer.h"
#include "member_BSpring.h"

using namespace BWE;

LayoutItem::LayoutItem()
{
	align = Align_Center;
	finishWidth = true;
	finishHeight = true;
}
LayoutItem::LayoutItem(const LayoutItem& other)
{
	widget = other.widget;
	layout = other.layout;
	spring = other.spring;
	align = other.align;
	finishWidth = other.finishWidth;
	finishHeight = other.finishHeight;
}
LayoutItem::~LayoutItem()
{

}

void LayoutItem::clear()
{
	widget = 0;
	layout = 0;
	spacer = 0;
	spring = 0;
}
bool LayoutItem::empty() const
{
	return !widget && !layout && spacer && !spring;
}
bool LayoutItem::ignored() const
{
	if (widget)
		return !widget->visible();
	if (layout)
		return !layout->able();
	if (spacer)
		return !spacer->able();
	if (spring)
		return !spring->able();
	return true;
}

void LayoutItem::attach(BWidget* host)
{
	if (host)
	{
		if (widget)
			host->addChild(widget);
		if (layout)
			layout->setHost(host);
	}
}
void LayoutItem::detach(BWidget* host)
{
	if (host)
	{
		if (widget)
			host->removeChild(widget);
		if (layout)
			layout->setHost(0);
		if (spacer)
			spacer_member(spacer)->layout = 0;
		if (spring)
			spring_member(spring)->layout = 0;
	}
}

bool LayoutItem::prepare(int remain)
{
	finishHeight = false;
	finishWidth = false;
	if (this->ignored())
	{
		finishHeight = true;
		finishWidth = true;
		return false;
	}
	if (this->spring && remain < 0)
	{
		finishHeight = true;
		finishWidth = true;
		return false;
	}
	BSize size = this->size();
	BSize sizeHint = this->sizeHint();
	BSize minSize = this->minSize();
	BSize maxSize = this->maxSize();
	BSizePolicy policy = sizePolicy();
	realSize = bLimit(sizeHint, minSize, maxSize);

	if (policy.widthPolicy() == Policy_Fixed)
	{
		finishWidth = true;
		realSize.width() = bLimit(size.width(), minSize.width(), maxSize.width());
	}
	if (policy.widthPolicy() == Policy_Preferred)
	{
		finishWidth = true;
		realSize.width() = sizeHint.width();
	}

	if (policy.heightPolicy() == Policy_Fixed)
	{
		finishHeight = true;
		realSize.height() = bLimit(size.height(), minSize.height(), maxSize.height());
	}
	if (policy.heightPolicy() == Policy_Preferred)
	{
		finishHeight = true;
		realSize.height() = sizeHint.height();
	}
	return true;
}

BSize LayoutItem::size() const
{
	if(widget)
		return widget->size();
	if(layout)
		return layout->size();
	if (spacer)
		return spacer->rect().size();
	if(spring)
		return spring->rect().size();
	return BSize(0, 0);
}
BSize LayoutItem::minSize() const
{
	if(widget)
		return widget->minSize();
	if(layout)
		return layout->minSize();
	if (spacer)
		return spacer->minSize();
	if(spring)
		return spring->minSize();
	return BSize(0, 0);
}
BSize LayoutItem::maxSize() const
{
	if(widget)
		return widget->maxSize();
	if(layout)
		return layout->maxSize();
	if (spacer)
		return spacer->maxSize();
	if(spring)
		return spring->maxSize();
	return BSize(999999, 999999);
}
BSize LayoutItem::sizeHint() const
{
	if (widget)
		return widget->sizeHint();
	if (layout)
		return layout->sizeHint();
	if (spacer)
		return spacer->sizeHint();
	if (spring)
		return spring->sizeHint();
	return BSize();
}
BSizePolicy LayoutItem::sizePolicy() const
{
	if(widget)
		return widget->sizePolicy();
	if(layout)
		return layout->sizePolicy();
	if (spacer)
		return spacer->sizePolicy();
	if(spring)
		return spring->sizePolicy();
	return BSizePolicy();
}
BSizeStretch LayoutItem::sizeStretch() const
{
	if(widget)
		return widget->sizeStretch();
	if(layout)
		return layout->sizeStretch();
	if (spacer)
		return spacer->sizeStretch();
	if(spring)
		return spring->sizeStretch();
	return 0;
}

void LayoutItem::adjust(int x, int y, int w, int h)
{
	rect.set(x, y, w, h);
	if(widget)
	{
		const BSizePolicy& sizePolicy = widget->sizePolicy();
		BSize minSize = widget->minSize();
		BSize maxSize = widget->maxSize();
		BSize size = rect.size();
		size.limit(minSize, maxSize);

		Policy widthPolicy = widget->sizePolicy().widthPolicy();
		if (widthPolicy == Policy_Fixed)
			size.setWidth(realSize.width());
		else if (widthPolicy == Policy_Minimum)
			size.setWidth(minSize.width());
		else if (widthPolicy == Policy_Maximum)
			size.setWidth(maxSize.width());

		Policy heightPolicy = widget->sizePolicy().heightPolicy();
		if (heightPolicy == Policy_Fixed)
			size.setHeight(realSize.height());
		else if (heightPolicy == Policy_Minimum)
			size.setHeight(minSize.height());
		else if (heightPolicy == Policy_Maximum)
			size.setHeight(maxSize.height());

		BRect realRect = rect.align(align, size);
		widget->setPos(realRect.pos());
		widget->setSize(realRect.size());
	}
	if(layout)
	{
		layout->setRect(rect);
		layout->adjust();
	}
	if (spacer)
	{
		if (spacer->name() == "debug")
			int a = 0;
		const BSizePolicy& sizePolicy = spacer->sizePolicy();
		BSize size = rect.size();

		if (sizePolicy.widthPolicy() == Policy_Fixed)
			size.width() = spacer->size().width();

		if (sizePolicy.heightPolicy() == Policy_Fixed)
			size.height() = spacer->size().height();

		BRect realRect = rect.align(align, size);
		spacer->setRect(realRect);
	}
	if(spring)
	{
		spring->setRect(rect);
	}
}

void LayoutItem::operator = (BWidget* widget)
{
	this->widget = widget;
	this->layout = 0;
	this->spacer = 0;
	this->spring = 0;
}
void LayoutItem::operator = (BLayout* layout)
{
	this->widget = 0;
	this->layout = layout;
	this->spacer = 0;
	this->spring = 0;
}
void LayoutItem::operator = (BSpacer* spacer)
{
	this->widget = 0;
	this->layout = 0;
	this->spacer = spacer;
	this->spring = 0;
}
void LayoutItem::operator = (BSpring* spring)
{
	this->widget = 0;
	this->layout = 0;
	this->spacer = 0;
	this->spring = spring;
}

bool LayoutItem::operator == (const BObject* object) const
{
	return widget == object || layout == object || spacer == object || spring == object;
}
bool LayoutItem::operator == (const BWidget* widget) const
{
	return this->widget == widget;
}
bool LayoutItem::operator == (const BLayout* layout) const
{
	return this->layout == layout;
}
bool LayoutItem::operator == (const BSpacer* spacer) const
{
	return this->spacer == spacer;
}
bool LayoutItem::operator == (const BSpring* spring) const
{
	return this->spring == spring;
}

bool LayoutItem::operator != (const BObject* object) const
{
	return widget != object && layout != object && spacer != object && spring != object;
}
bool LayoutItem::operator != (const BWidget* widget) const
{
	return this->widget != widget;
}
bool LayoutItem::operator != (const BLayout* layout) const
{
	return this->layout != layout;
}
bool LayoutItem::operator != (const BSpacer* spacer) const
{
	return this->spacer != spacer;
}
bool LayoutItem::operator != (const BSpring* spring) const
{
	return this->spring != spring;
}

member_BLayout::member_BLayout(BLayout* layout)
{
	boss = layout;
	host = 0;
	parent = 0;

	border = 0;
	space = 0;
	host = 0;
	minSize.set(0, 0);
	maxSize.set(999999, 999999);
	dirty = true;
}
member_BLayout::~member_BLayout()
{

}

